﻿using NCP.Core;
using NCP.Core.DataUtil;
using NCP.Core.Exceptions;
using NCP.Core.Extensions;
using NCP.Core.IoC;
using NCP.Model;
using NCP.Util;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;

namespace NCP.Service
{
    public class GroupPurchaseService : IService
    {
        private SqlSugarClient _client;
        public GroupPurchaseService()
        {
            _client = DbHelper.GetSqlSugarClient();
        }

        public string GetNewGPCode()
        {
            int seq = _client.Ado.GetInt("SELECT NEXT VALUE FOR Seq_GroupPurchase_Code");

            return DateTime.Now.ToString("yyyyMMdd") + seq.ToString().PadLeft(4, '0');
        }

        public GroupPurchase GetGroupPurchase(string gpCode)
        {
            return _client.Queryable<GroupPurchase>().Where(t => t.Code == gpCode).First();
        }

        /// <summary>
        /// 获取所有药品信息，json格式
        /// </summary>
        /// <returns></returns>
        public string DrugCompareGetAllBaseInfo()
        {
            var baseInfo = _client.Queryable<PhaBaseInfo>().Where(x => x.ValidFlag == "1").ToList();
            List<string> rows = new List<string>();
            foreach (var info in baseInfo)
            {
                string code = info.DrugCode;
                string name = $"{info.DrugName}【{info.Specs}】￥{info.UnitPrice.ToString("0.######")}";
                rows.Add("{'value':'" + code + "','title':'" + name + "'}");
            }
            return $"[{string.Join(",", rows.ToArray())}]";
        }

        /// <summary>
        /// 获取集采批次药品，json格式
        /// </summary>
        /// <returns></returns>
        public string DrugCompareGetGroupDrugInfo(string gpCode)
        {
            var json = _client.Queryable<GroupDrugInfo>().Where(x => x.GpCode == gpCode).Select(x => x.DrugCode).ToJson();
            return json;
        }

        public object GroupDrugAllDrugList(string gpCode)
        {
            var data = _client.Queryable<PhaBaseInfo>()
                .LeftJoin<GroupDrugInfo>((pb, gd) => pb.DrugCode == gd.DrugCode && gd.GpCode == gpCode)
                .Where((pb, gd) => pb.ValidFlag == "1" && SqlFunc.EqualsNull(gd.DrugCode, null))
                .Select((pb, gd) => (dynamic)new { pb.DrugCode, pb.DrugName, pb.Specs, pb.UnitPrice, pb.SpellCode, pb.ProducerName })
                .Mapper(x => { x.TaskQTY = 0; x.TaskRatio = 0; })
                .ToArray();

            return data;
        }


        public object GroupDrugChoseDrugList(string gpCode)
        {
            var data = _client.Queryable<PhaBaseInfo>()
                .InnerJoin<GroupDrugInfo>((pb, gd) => pb.DrugCode == gd.DrugCode && gd.GpCode == gpCode)
                .Select((pb, gd) => (dynamic)new { pb.DrugCode, pb.DrugName, pb.Specs, pb.UnitPrice, pb.SpellCode, pb.ProducerName, gd.TaskQTY, gd.TaskRatio })
                .Mapper(x => x.GpCode = gpCode)
                .ToArray();

            return data;
        }

        /// <summary>
        /// 获取集采批次药品
        /// </summary>
        /// <returns></returns>
        public DataTable DrugTaskBaseInfo(string gpCode)
        {
            DataTable dt = _client.Queryable<GroupPurchase>()
                .InnerJoin<GroupDrugInfo>((gp, gd) => gp.Code == gd.GpCode)
                .InnerJoin<PhaBaseInfo>((gp, gd, pb) => gd.DrugCode == pb.DrugCode)
                .Where(gp => gp.Code == gpCode)
                .Select((gp, gd, pb) => new { gd.DrugCode, pb.DrugName, pb.Specs, pb.UnitPrice, gd.TaskQTY })
                .ToDataTable();

            return dt;
        }



        public List<GroupPurchase> GetAllGroupPurchases()
        {
            return _client.Queryable<GroupPurchase>().ToList();
        }

        public int SaveGroupPurchase(GroupPurchase item, bool isNew)
        {
            MessageException.CheckNullException(item.Code, "编码不能为空!");
            MessageException.CheckNullException(item.Name, "名称不能为空!");
            Member oper = MemberUtil.GetCurrentMember();
            item.BeginDate = item.BeginDate.Date;
            item.EndDate = item.EndDate.Date.AddDays(1).AddSeconds(-1);
            MessageException.CheckException(item.BeginDate >= item.EndDate, $"开始时间必须小于结束时间!");
            GroupPurchase oldItem = null;
            if (isNew)
            {
                bool anyItem = _client.Queryable<GroupPurchase>().Where(x => x.Code == item.Code).Any();
                MessageException.CheckException(anyItem, $"编码({item.Code})已存在，请更换后重试!");
            }
            else
            {
                oldItem = _client.Queryable<GroupPurchase>().Where(x => x.Code == item.Code).First();
                MessageException.CheckNullException(oldItem, "获取原始信息失败!");
                MessageException.CheckException(oldItem.Enabled == "1", "集采批次已启用，不能修改!");
            }

            //判断时间是否与原数据冲突
            /*
            var ext = _client.Queryable<GroupPurchase>().Where(x => item.Code != x.Code && (SqlFunc.Between(item.BeginDate, x.BeginDate, x.EndDate) || SqlFunc.Between(item.EndDate, x.BeginDate, x.EndDate) || SqlFunc.Between(x.BeginDate, item.BeginDate, item.EndDate) || SqlFunc.Between(x.EndDate, item.BeginDate, item.EndDate))).Select(x => x.Name).ToList();
            if (ext.Count > 0)
            {
                MessageException.CheckException(true, $"设置的时间与({string.Join(",", ext)})存在冲突，请确认后重试!");
            }
            */
            item.OperCode = oper?.Code;
            item.OperDate = DateTime.Now;
            int result = 0;
            _client.BeginTran();
            try
            {

                #region 操作日志

                SysOperLogService.WriteSysOperLog(new SysOperLog
                {
                    EventType = oldItem == null ? "新增集采批次信息" : "修改集采批次信息",
                    EventCon = oldItem == null ? "新增" : "修改",
                    OldCon = oldItem == null ? null : JsonConvert.SerializeObject(oldItem),
                    NewCon = JsonConvert.SerializeObject(item)
                });

                #endregion

                if (oldItem == null)
                {
                    result = _client.Insertable(item).ExecuteCommand();
                }
                else
                {
                    result = _client.Updateable(item).ExecuteCommand();
                }

                _client.CommitTran();
            }
            catch
            {
                _client.RollbackTran();
                throw;
            }
            return result;
        }

        public DataTable ImportTemplet()
        {
            var data = _client.Queryable<PhaBaseInfo>()
                   .Where(pb => pb.ValidFlag == "1")
                   .Select(pb => (dynamic)new { 药品编码 = pb.DrugCode, 药品名称 = pb.DrugName, 规格 = pb.Specs, 单价 = pb.UnitPrice, 生产厂家 = pb.ProducerName, 任务量 = 0, 规定使用占比 = 0 })
                   .ToDataTable();

            return data;
        }
        public DataTable ExportDrug(string gpCode)
        {
            var data = _client.Queryable<PhaBaseInfo>()
                   .InnerJoin<GroupDrugInfo>((pb, gd) => pb.DrugCode == gd.DrugCode && gd.GpCode == gpCode)
                   //.Where(pb => pb.ValidFlag == "1")
                   .Select((pb, gd) => (dynamic)new { 药品编码 = pb.DrugCode, 药品名称 = pb.DrugName, 规格 = pb.Specs, 单价 = pb.UnitPrice, 生产厂家 = pb.ProducerName, 任务量 =gd.TaskQTY , 规定使用占比 = gd.TaskRatio })
                   .ToDataTable();

            return data;
        }

        public int ImportDrug(DataTable dt, string gpCode)
        {
            MessageException.CheckException(!dt.Columns.Contains("药品编码"), "导入文件不包含【药品编码】列!");
            MessageException.CheckException(!dt.Columns.Contains("任务量"), "导入文件不包含【任务量】列!");
            MessageException.CheckException(!dt.Columns.Contains("规定使用占比"), "导入文件不包含【规定使用占比】列!");
            var items = new List<GroupDrugInfo>();
            foreach (DataRow row in dt.Rows)
            {
                items.Add(new GroupDrugInfo
                {
                    GpCode = gpCode,
                    DrugCode = row["药品编码"].AsString(),
                    TaskQTY = row["任务量"].AsDecimal(0),
                    TaskRatio = row["规定使用占比"].AsDecimal(0),
                });
            }
            return SaveGroupDrug(items, gpCode, false, "批量导入");
        }

        public int DelGroupPurchase(string gpCode)
        {
            if (string.IsNullOrEmpty(gpCode))
                return 0;
            GroupPurchase oldItem = _client.Queryable<GroupPurchase>().Where(x => x.Code == gpCode).First();
            if (oldItem == null)
                return 0;

            //MessageException.CheckException(oldItem.Enabled == "1", "集采批次已启用，不能删除!");
            MessageException.CheckException(_client.Queryable<GroupDrugInfo>().Any(x => x.GpCode == gpCode), "集采批次中已维护药品，请删除所有药品后重试!");
            MessageException.CheckException(_client.Queryable<GroupMission>().Any(x => x.GpCode == gpCode && x.ValidFlag == "1"), "集采批次中已维护集采任务，请删除所有任务后重试!");
            MessageException.CheckException(_client.Queryable<GroupChoseDrugCompare>().Any(x => x.GpCode == gpCode), "集采批次中已维护中选药品与非中选药品对照，请删除所有信息后重试!");
            MessageException.CheckException(_client.Queryable<GroupVarietyDrugCompare>().Any(x => x.GpCode == gpCode), "集采批次中已维护中选药品与同品种药品对照，请删除所有信息后重试!");

            int result = 0;
            _client.BeginTran();
            try
            {
                #region 操作日志

                SysOperLogService.WriteSysOperLog(new SysOperLog
                {
                    EventType = "删除集采批次信息",
                    EventCon = "删除",
                    OldCon = JsonConvert.SerializeObject(oldItem)
                });

                #endregion

                //删除集采信息
                result = _client.Deleteable(oldItem).ExecuteCommand();

                _client.CommitTran();
            }
            catch
            {
                _client.RollbackTran();
                throw;
            }
            return result;
        }


        public int EnabledGroupPurchase(string gpCode)
        {
            GroupPurchase oldItem = _client.Queryable<GroupPurchase>().Where(x => x.Code == gpCode).First();
            MessageException.CheckNullException(oldItem, "获取采集批次信息失败!");
            MessageException.CheckException(oldItem.Enabled == "1", "集采批次已启用，请勿重复操作!");

            int result = 0;
            _client.BeginTran();
            try
            {
                #region 操作日志

                SysOperLogService.WriteSysOperLog(new SysOperLog
                {
                    EventType = "启用集采批次信息",
                    EventCon = "启用",
                    OldCon = JsonConvert.SerializeObject(oldItem)
                });

                #endregion

                oldItem.Enabled = "1";

                result = _client.Updateable(oldItem).UpdateColumns(x => x.Enabled).ExecuteCommand();

                _client.CommitTran();
            }
            catch
            {
                _client.RollbackTran();
                throw;
            }
            return result;
        }

        public int SaveCompare(string gpCode, string[] baseArray)
        {
            if (string.IsNullOrEmpty(gpCode))
                return 0;
            GroupPurchase oldItem = _client.Queryable<GroupPurchase>().Where(x => x.Code == gpCode).First();
            MessageException.CheckNullException(oldItem, "获取采集批次信息失败!");
            MessageException.CheckException(oldItem.Enabled == "1", "集采批次已启用，不能修改!");

            var oldItems = _client.Queryable<GroupDrugInfo>().Where(x => x.GpCode == gpCode).Select(x => x.DrugCode).ToArray();
            var newItems = new List<GroupDrugInfo>();
            foreach (var item in baseArray)
            {
                newItems.Add(new GroupDrugInfo
                {
                    GpCode = gpCode,
                    DrugCode = item
                });
            }


            int result = 0;
            _client.BeginTran();
            try
            {
                #region 操作日志

                SysOperLogService.WriteSysOperLog(new SysOperLog
                {
                    EventType = "修改集采批次药品信息",
                    EventCon = "修改",
                    OldCon = string.Join("^", oldItems),
                    NewCon = string.Join("^", baseArray)
                });

                #endregion

                //保存信息
                _client.Deleteable<GroupDrugInfo>().Where(x => x.GpCode == gpCode).ExecuteCommand();
                result = _client.Insertable(newItems).ExecuteCommand();

                _client.CommitTran();
            }
            catch
            {
                _client.RollbackTran();
                throw;
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="items">项目</param>
        /// <param name="gpCode">批次编码</param>
        /// <param name="apped">是否为附加</param>
        /// <param name="logMemo">日志备注</param>
        /// <returns></returns>
        public int SaveGroupDrug(List<GroupDrugInfo> items, string gpCode, bool apped = false, string logMemo = "")
        {
            if (items == null) items = new List<GroupDrugInfo>();

            GroupPurchase oldItem = _client.Queryable<GroupPurchase>().Where(x => x.Code == gpCode).First();
            MessageException.CheckNullException(oldItem, "获取采集批次信息失败!" + gpCode);
            MessageException.CheckException(oldItem.Enabled == "1", "集采批次已启用，不能修改!");

            var oldItems = _client.Queryable<GroupDrugInfo>().Where(x => x.GpCode == gpCode).ToList();

            _client.BeginTran();
            try
            {
                #region 操作日志

                string oldCon = "";
                string newCon = "";
                oldItems.ForEach(x => oldCon += $"{x.DrugCode},{x.TaskQTY.ToString("0.######")},{x.TaskRatio.ToString("0.######")}^");
                items.ForEach(x => newCon += $"{x.DrugCode},{x.TaskQTY.ToString("0.######")},{x.TaskRatio.ToString("0.######")}^");
                SysOperLogService.WriteSysOperLog(new SysOperLog
                {
                    EventType = "修改集采批次药品信息",
                    EventCon = $"修改采集批次:{oldItem.Code},{oldItem.Name},Apped:{apped}",
                    OldCon = oldCon.TrimEnd('^'),
                    NewCon = newCon.TrimEnd('^'),
                    Memo = logMemo
                });

                #endregion
                //删除信息
                if (!apped)
                {
                    List<string> delItems = new List<string>();
                    foreach (var item in oldItems)
                    {
                        if (!items.Exists(x => x.DrugCode == item.DrugCode))
                        {
                            delItems.Add(item.DrugCode);
                        }
                    }
                    if (delItems.Count > 0)
                    {
                        //检查是否维护了其他的数据。不能删除
                        string errMsg = "";
                        foreach (var delItem in delItems)
                        {
                            if (_client.Queryable<GroupMission>().Any(x => x.GpCode == gpCode && x.DrugCode == delItem && x.ValidFlag == "1"))
                            {
                                errMsg += $"【{GetBaseName(delItem)}】 已经维护了集采任务，不能删除; ";
                            }
                            if (_client.Queryable<GroupChoseDrugCompare>().Any(x => x.GpCode == gpCode && x.ChosedrugCode == delItem))
                            {
                                errMsg += $"【{GetBaseName(delItem)}】 已经维护了中选药品与非中选药品对照，不能删除; ";
                            }
                            if (_client.Queryable<GroupVarietyDrugCompare>().Any(x => x.GpCode == gpCode && x.ChoseDrugCode == delItem))
                            {
                                errMsg += $"【{GetBaseName(delItem)}】 已经维护了中选药品与同品种药品对照，不能删除; ";
                            }
                        }
                        MessageException.CheckException(errMsg != "", errMsg);

                        //删除
                        _client.Deleteable<GroupDrugInfo>().Where(x => x.GpCode == gpCode && delItems.Contains(x.DrugCode)).ExecuteCommand();
                    }
                }
                //保存信息
                var insertItems = new List<GroupDrugInfo>();
                var updateItems = new List<GroupDrugInfo>();
                foreach (var item in items)
                {
                    item.GpCode = gpCode;
                    if (oldItems.Exists(x => x.DrugCode == item.DrugCode))
                    {
                        updateItems.Add(item);
                    }
                    else
                    {
                        insertItems.Add(item);
                    }
                }
                _client.Insertable(insertItems).ExecuteCommand();
                _client.Updateable(updateItems).WhereColumns(x => new { x.GpCode, x.DrugCode }).ExecuteCommand();

                _client.CommitTran();
            }
            catch
            {
                _client.RollbackTran();
                throw;
            }
            return 1;
        }

        private string GetBaseName(string drugCode)
        {
            return _client.Queryable<PhaBaseInfo>().Where(x => x.DrugCode == drugCode).Select(x => x.DrugName).First();
        }

        public List<GroupPurchase> GetGroupPurchasePageList(string setpc, Expressionable<GroupPurchase> exp, PageModel page, string orderFields = "Year desc,BeginDate desc")
        {

            int count = 0;
            if (setpc == "0" || setpc == null)//全部
            {

                MemberService memberService = new MemberService();
                var result = _client.Queryable<GroupPurchase>()
                    .Where(exp.ToExpression())
                    .Mapper(x => x.Oper = memberService.GetMemberNameByCodeCache(x.OperCode))
                    .OrderBy(orderFields)
                    .ToPageList(page.PageIndex, page.PageSize, ref count);
                page.TotalCount = count;
                return result;
            }
            else if (setpc == "1")//正在执行
            {

                MemberService memberService = new MemberService();
                var result = _client.Queryable<GroupPurchase>()
                    .Where(exp.ToExpression())
                    .Where(p => SqlFunc.Between(DateTime.Now, p.BeginDate, p.EndDate))
                    .Mapper(x => x.Oper = memberService.GetMemberNameByCodeCache(x.OperCode))
                    .OrderBy(orderFields)
                    .ToPageList(page.PageIndex, page.PageSize, ref count);
                page.TotalCount = count;
                return result;
            }
            else
            {

                MemberService memberService = new MemberService();
                var result = _client.Queryable<GroupPurchase>()
                    .Where(exp.ToExpression())
                    .Where(p => (p.BeginDate > DateTime.Now || p.EndDate <= DateTime.Now))
                    .Mapper(x => x.Oper = memberService.GetMemberNameByCodeCache(x.OperCode))
                    .OrderBy(orderFields)
                    .ToPageList(page.PageIndex, page.PageSize, ref count);
                page.TotalCount = count;
                return result;
            }
        }

        public DataTable GetGPListExport()
        {
            var data = _client.Queryable<GroupPurchase>()
                   .Select(pb => new { 编码 = pb.Code, 名称 = pb.Name, 年份 = pb.Year, 开始日期 = pb.BeginDate, 结束日期 = pb.EndDate, 状态 = SqlFunc.IF(pb.Enabled == "1").Return("已启用").End("未启用") })
                   .ToDataTable();

            return data;
        }
        public virtual List<GroupPurchase> GetAllGroupPurchase(Expressionable<GroupPurchase> exp, string orderFields = "Year desc,BeginDate desc")
        {
            MemberService memberService = new MemberService();
            return _client.Queryable<GroupPurchase>()
                .Where(exp.ToExpression())
                .Mapper(x => x.Oper = memberService.GetMemberNameByCodeCache(x.OperCode))
                .OrderBy(orderFields)
                .ToList();
        }
    }
}
